/*
 ------------------------------------------------------------------------------
 Copyright (C) 2006-2007 Team Blur.

 This file is part of the Quantum Engine source code.

 The Quantum Engine source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Quantum Engine source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Quantum Engine source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


#ifndef __CLIENT_H__
#define __CLIENT_H__


#include "../core/core_main.h"
#include "../game/client/cg_public.h"
#include "../collision/cm_public.h"
#include "../renderer/r_public.h"
#include "../sound/s_public.h"
#include "../gui/gui_public.h"
#include "../editor/ed_public.h"
#include "../network/net_main.h"

#define RESEND_TIMEOUT					3000

// Maximum number of mouse samples that can be blended
#define MAX_MOUSE_SAMPLES				8

// Connection states
typedef enum {
	CS_UNINITIALIZED,							// Only before initialization or for dedicated servers
	CS_DISCONNECTED,							// Not talking to a server
	CS_CONNECTED,								// Connection established, getting game state
	CS_LOADING,									// Only during level load, never during main loop
	CS_PRIMED,									// Got game state, waiting for first snapshot
	CS_ACTIVE									// Game views should be displayed
} connectionState_t;

typedef struct {
	int						userCmdNumber;		// User command number when packet was sent
} packet_t;

// The clientActive_t structure is wiped completely at every level change,
// potentially several times during an established connection
typedef struct {
	int						time;
	int						oldTime;

	int						timeDelta;

	// Snapshot
	bool					snapshotAvailable;
	bool					snapshotExtrapolated;

	bool					snapshotValid;
	int						snapshotSequence;
	int						snapshotTime;

	// The client maintains its own idea of view angles, which are sent to the
	// server each frame.
	// It is cleared to 0 upon entering each level.
	// The server sends a delta each frame which is added to the locally
	// tracked view angles to account for standing on rotating objects, and
	// teleport direction changes.
	odAngles				viewAngles;

	// Mouse movement
	int						mouseIndex;

	int						mouseX[MAX_MOUSE_SAMPLES];
	int						mouseY[MAX_MOUSE_SAMPLES];

	// User commands
	userCmd_t				userCmds[USERCMD_BACKUP];
	int						userCmdNumber;

	// Packets information
	packet_t				packets[PACKET_BACKUP];

	// Stuff communicated by the game module
	int						gameDeltaAngles[3];
	float					gameSensitivity;

	// Server information
	int						serverId;
	int						serverFPS;
	char					serverInfo[MAX_STRING_LENGTH];

	bool					serverPure;
	ulong					serverPackChecksums[MAX_PACK_FILES];
} clientActive_t;

// The clientStatic_t structure is never wiped, and is used even when no client
// connection is active at all
typedef struct {
	connectionState_t		state;				// Connection status
	
	ENetAddress				serverAddress;
	ENetHost				*client;//client socket
	ENetPeer				*server;//server we connect to

	int						frameTime;
	int						frameMsec;
	int						frameCount;

	char					serverName[128];	// Name of server from original connect

	// Renderer and sound system information
	glConfig_t				glConfig;
	alConfig_t				alConfig;

	// Materials required for console and cinematic drawing
	material_t *			whiteMaterial;
	material_t *			consoleMaterial;
	material_t *			charsetMaterial;
	material_t *			cinematicMaterial;
} clientStatic_t;

// ============================================================================

extern clientActive_t		cl;
extern clientStatic_t		cls;

extern cvar_t *				cl_aviDemo;
extern cvar_t *				cl_forceAviDemo;
extern cvar_t *				cl_timeNudge;
extern cvar_t *				cl_showTimeDelta;
extern cvar_t *				cl_showMessages;
extern cvar_t *				cl_showFPS;
extern cvar_t *				cl_playerName;
extern cvar_t *				cl_password;
extern cvar_t *				cl_rate;
extern cvar_t *				cl_snapshots;
extern cvar_t *				cl_maxPackets;
extern cvar_t *				cl_packetDup;
extern cvar_t *				cl_allowDownload;
extern cvar_t *				cl_deltaCompress;
extern cvar_t *				cl_timeOut;
extern cvar_t *				cl_rconAddress;
extern cvar_t *				cl_rconPassword;

extern cvar_t *				in_freeLook;
extern cvar_t *				in_alwaysRun;
extern cvar_t *				in_pitchSpeed;
extern cvar_t *				in_yawSpeed;
extern cvar_t *				in_angleSpeedKey;

extern cvar_t *				m_showRate;
extern cvar_t *				m_showMove;
extern cvar_t *				m_sensitivity;
extern cvar_t *				m_smooth;
extern cvar_t *				m_accel;
extern cvar_t *				m_pitch;
extern cvar_t *				m_yaw;
extern cvar_t *				m_strafe;

void				CL_InitAll (void);
void				CL_ShutdownAll (void);

void				CL_Disconnect (bool restart);

void				CL_SendReliableCommand (const char *fmt, ...);

void				CL_RequestNextDownload (void);
void				CL_RequestDownloads (void);

void				CL_UpdateScreen (void);

void				CL_BuildUserCmd (void);

void				CL_SendPacket (void);
void				CL_SendCommands (void);

void				CL_ParseServerMessage (ByteBuffer *msg);


/*
 ==============================================================================

 CINEMATIC

 ==============================================================================
*/
/*
// Runs a frame of the cinematic but does not draw it.
// Will automatically stop the cinematic if either the end has been reached or
// an error occurred.
void				CIN_RunCinematic (void);

// Draws the current frame of the cinematic
void				CIN_DrawCinematic (void);

// Plays a cinematic
void				CIN_PlayCinematic (const char *name);

// Stops a cinematic
void				CIN_StopCinematic (void);

// Initializes the cinematic code
void				CIN_Init (void);

// Shuts down the cinematic code
void				CIN_Shutdown (void);
*/
/*
 ==============================================================================

 CONSOLE

 ==============================================================================
*/

// Prints text to the console.
// Handles cursor positioning, line wrapping, colored text, etc...
void				Con_Print (const char *text);

// Forces the console off
void				Con_Close (void);

// Decides on the height of the console
void				Con_RunConsole (void);

// Draws the console, or notify lines if toggled off
void				Con_DrawConsole (void);

// Handles console key down and char events
void				Con_KeyDownEvent (int key);
void				Con_CharEvent (int c);

// Toggles the console on/off
void				Con_ToggleConsole_f (void);

// Initializes the console
void				Con_Init (void);

// Shuts down the console
void				Con_Shutdown (void);


/*
 ==============================================================================

 INPUT

 ==============================================================================
*/

typedef struct {
	int						keys[2];			// Key nums holding it down

	int						downTime;			// Button down msec timestamp
	int						upTime;				// Button up msec timestamp

	bool					active;				// Current state
	bool					wasPressed;			// Set when down, not cleared when up
} keyButton_t;

extern keyButton_t			in_moveForward;
extern keyButton_t			in_moveBack;
extern keyButton_t			in_moveRight;
extern keyButton_t			in_moveLeft;
extern keyButton_t			in_moveUp;
extern keyButton_t			in_moveDown;
extern keyButton_t			in_turnRight;
extern keyButton_t			in_turnLeft;
extern keyButton_t			in_lookUp;
extern keyButton_t			in_lookDown;
extern keyButton_t			in_speed;
extern keyButton_t			in_strafe;
extern keyButton_t			in_buttons[32];

extern bool					in_mouseLook;

// Returns the fraction of the frame that the given key button was down
float				IN_KeyState (keyButton_t *kb);

// Moves the GUI cursor or accumulates mouse movement
void				IN_MouseMove (int x, int y);

// Clears accumulated mouse movement
void				IN_ClearMouseMovement (void);

// Generates key events for the given mouse button state
void				IN_MouseButtonEvent (int buttonState);

// Generates key events for the given mouse wheel delta
void				IN_MouseWheelEvent (int wheelDelta);

// Ensures mouse input is either activated or deactivated and finds mouse
// movement.
// Will release the mouse cursor if the game is running in windowed mode and
// the console is down.
void				IN_MouseFrame (void);

// Clears mouse input state
void				IN_ClearStates (void);

// Activates or deactivates mouse input.
// This should be called when the main window gains or loses focus.
void				IN_Activate (bool active);

// Adds input commands
void				IN_AddCommands (void);

// Removes input commands
void				IN_RemoveCommands (void);

// Initializes the input subsystem
void				IN_Init (void);

// Shuts down the input subsystem
void				IN_Shutdown (void);

/*
 ==============================================================================

 INTERFACE TO GAME LIBRARY

 ==============================================================================
*/

extern cgExport_t *			cg;

void				CG_LoadLevel (void);
void				CG_FreeLevel (void);

void				CG_RunFrame (void);

void				CG_Init (void);
void				CG_Shutdown (void);


#endif	// __CLIENT_H__
